template<class T>
struct TObjectPoolBlock
{
	struct THeader
	{
		int mPageID;
		ubyte mBlockID; //1 byte for blockID
	} mHeader;
	//memory
	char mMemory[sizeof(T)];
};

template<class T>
class TObjectPoolPage
{
private:
	Set mUsingBlock;
	TObjectPoolBlock<T> mBlocks[32];
public:
	bool IsFull(void)
	{
		return mUsingBlock.GetMask() == Invalid;
	}

	UnSafePtr CreateObjectInPage(uint pageID)
	{
		for(char j = 0; j!=32; ++j)
		{
			if(!mUsingBlock.In(j))
			{
				mUsingBlock.Include(j); // meke use
				mBlocks[j].mHeader.mPageID = (uint)pageID;
				mBlocks[j].mHeader.mBlockID = j;
				return &mBlocks[j].mMemory[0]; // mMemory[0..4] - save pageID and blockID, mMemory[0+4] is data
			}
		}
		//this error!!!
		iError("not find free block");
		return 0;
	}

	void DisposeObjectInPage(uint objID)
	{
		mUsingBlock.Exclude(objID);
	}
};

/*-------------------------------------------------------------------------
| ObjectPool:
| ------------
| Object pool
---------------------------------------------------------------------------*/
template<class T>
class TObjectPool : public TArrayAllocation<TObjectPoolPage<T> >
{
private:
	TObjectPool(const TObjectPool<T>& copy)
	{/*noncopyable*/}
public:
	TObjectPool(void) : TArrayAllocation()
	{
	}

	UnSafePtr CreateObjectInPool(void)
	{
		lock(this);
		uint pageID = 0;
		for(uint i = 0; i!=Length(); ++i)
		{
				if(!mBuffer[i].IsFull())
				{
					return mBuffer[i].CreateObjectInPage(i);
				}
		}
		//if not alloc in existing pages need alloc new page
		pageID = Alloc(Length()+1)-1;
		return mBuffer[pageID].CreateObjectInPage(pageID);
	}

	void DisposeObjectInPool(UnSafePtr p)
	{
		lock(this);
		void* addr = (UnSafePtr)((uint)p - sizeof(TObjectPoolBlock<T>::THeader));
		TObjectPoolBlock<T>* block = static_cast<TObjectPoolBlock<T>*>(addr);
		const TObjectPoolBlock<T>::THeader & header = block->mHeader;
		mBuffer[header.mPageID].DisposeObjectInPage(header.mBlockID);
	}
};

#define MakeObjectPool(X)
/*
#define MakeObjectPool(X) \
	private: \
	static TObjectPool<X>& GetPool(void) \
	{ \
                static ref<TObjectPool<X> > pool(new TObjectPool<X>()); \
		return pool.operator *(); \
	} \
	public: \
	void operator delete(void* p) \
	{ \
		GetPool().DisposeObjectInPool(p); \
	} \
	void* operator new(uint) \
	{ \
		return GetPool().CreateObjectInPool(); \
	}
*/
